//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package io.lumine.xikage.mythicmobs.utils.promise;

import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import io.lumine.xikage.mythicmobs.utils.interfaces.Delegate;
import io.lumine.xikage.mythicmobs.utils.logging.Log;
import io.lumine.xikage.mythicmobs.utils.plugin.LoaderUtils;
import io.lumine.xikage.mythicmobs.utils.tasks.LumineExecutors;
import io.lumine.xikage.mythicmobs.utils.tasks.Ticks;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.Nullable;

import javax.annotation.Nonnull;

final class LuminePromise<V> implements Promise<V> {
    private static final Consumer<Throwable> EXCEPTION_CONSUMER = (throwable) -> {
        Log.severe("[调度系统] 执行任务出错，请完整截图发给维护者");
        throwable.printStackTrace();
    };
    private final AtomicBoolean supplied = new AtomicBoolean(false);
    private final AtomicBoolean cancelled = new AtomicBoolean(false);
    @Nonnull
    private final CompletableFuture<V> fut;

    @Nonnull
    static <U> LuminePromise<U> empty() {
        return new LuminePromise();
    }

    @Nonnull
    static <U> LuminePromise<U> completed(@Nullable U value) {
        return new LuminePromise(value);
    }

    @Nonnull
    static <U> LuminePromise<U> exceptionally(@Nonnull Throwable t) {
        return new LuminePromise(t);
    }

    @Nonnull
    static <U> Promise<U> wrapFuture(@Nonnull Future<U> future) {
        if (future instanceof CompletableFuture) {
            return new LuminePromise(((CompletableFuture)future).thenApply(Function.identity()));
        } else if (future instanceof CompletionStage) {
            CompletionStage<U> fut = (CompletionStage)future;
            return new LuminePromise(fut.toCompletableFuture().thenApply(Function.identity()));
        } else if (future instanceof ListenableFuture) {
            ListenableFuture<U> fut = (ListenableFuture)future;
            final LuminePromise<U> promise = empty();
            promise.supplied.set(true);
            Futures.addCallback(fut, new FutureCallback<U>() {
                public void onSuccess(@Nullable U result) {
                    promise.complete(result);
                }

                public void onFailure(@Nonnull Throwable t) {
                    promise.completeExceptionally(t);
                }
            });
            return promise;
        } else if (future.isDone()) {
            try {
                return completed(future.get());
            } catch (ExecutionException var3) {
                return exceptionally(var3);
            } catch (InterruptedException var4) {
                throw new RuntimeException(var4);
            }
        } else {
            Objects.requireNonNull(future);
            return Promise.supplyingExceptionallyAsync(future::get);
        }
    }

    private LuminePromise() {
        this.fut = new CompletableFuture();
    }

    private LuminePromise(@Nullable V v) {
        this.fut = CompletableFuture.completedFuture(v);
        this.supplied.set(true);
    }

    private LuminePromise(@Nonnull Throwable t) {
        (this.fut = new CompletableFuture()).completeExceptionally(t);
        this.supplied.set(true);
    }

    private LuminePromise(@Nonnull CompletableFuture<V> fut) {
        this.fut = (CompletableFuture)Objects.requireNonNull(fut, "future");
        this.supplied.set(true);
        this.cancelled.set(fut.isCancelled());
    }

    private void executeSync(@Nonnull Runnable runnable) {
        if (ThreadContext.forCurrentThread() == ThreadContext.SYNC) {
            LumineExecutors.wrapRunnable(runnable).run();
        } else {
            LumineExecutors.sync().execute(runnable);
        }

    }

    private void executeAsync(@Nonnull Runnable runnable) {
        LumineExecutors.asyncLumine().execute(runnable);
    }

    private void executeDelayedSync(@Nonnull Runnable runnable, long delayTicks) {
        if (delayTicks <= 0L) {
            this.executeSync(runnable);
        } else {
            Bukkit.getScheduler().runTaskLater(LoaderUtils.getPlugin(), LumineExecutors.wrapRunnable(runnable), delayTicks);
        }

    }

    private void executeDelayedAsync(@Nonnull Runnable runnable, long delayTicks) {
        if (delayTicks <= 0L) {
            this.executeAsync(runnable);
        } else {
            Bukkit.getScheduler().runTaskLaterAsynchronously(LoaderUtils.getPlugin(), LumineExecutors.wrapRunnable(runnable), delayTicks);
        }

    }

    private void executeDelayedSync(@Nonnull Runnable runnable, long delay, TimeUnit unit) {
        if (delay <= 0L) {
            this.executeSync(runnable);
        } else {
            Bukkit.getScheduler().runTaskLater(LoaderUtils.getPlugin(), LumineExecutors.wrapRunnable(runnable), Ticks.from(delay, unit));
        }

    }

    private void executeDelayedAsync(@Nonnull Runnable runnable, long delay, TimeUnit unit) {
        if (delay <= 0L) {
            this.executeAsync(runnable);
        } else {
            LumineExecutors.asyncLumine().schedule(LumineExecutors.wrapRunnable(runnable), delay, unit);
        }

    }

    private boolean complete(V value) {
        return !this.cancelled.get() && this.fut.complete(value);
    }

    private boolean completeExceptionally(@Nonnull Throwable t) {
        return !this.cancelled.get() && this.fut.completeExceptionally(t);
    }

    private void markAsSupplied() {
        if (!this.supplied.compareAndSet(false, true)) {
            throw new IllegalStateException("Promise is already being supplied.");
        }
    }

    public boolean cancel(boolean mayInterruptIfRunning) {
        this.cancelled.set(true);
        return this.fut.cancel(mayInterruptIfRunning);
    }

    public boolean isCancelled() {
        return this.fut.isCancelled();
    }

    public boolean isDone() {
        return this.fut.isDone();
    }

    public V get() throws InterruptedException, ExecutionException {
        return this.fut.get();
    }

    public V get(long timeout, @Nonnull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        return this.fut.get(timeout, unit);
    }

    public V join() {
        return this.fut.join();
    }

    public V getNow(V valueIfAbsent) {
        return this.fut.getNow(valueIfAbsent);
    }

    public CompletableFuture<V> toCompletableFuture() {
        return this.fut.thenApply(Function.identity());
    }

    public void close() {
        this.cancel();
    }

    public boolean hasTerminated() {
        return this.isCancelled();
    }

    @Nonnull
    public Promise<V> supply(@Nullable V value) {
        this.markAsSupplied();
        this.complete(value);
        return this;
    }

    @Nonnull
    public Promise<V> supplyException(@Nonnull Throwable exception) {
        this.markAsSupplied();
        this.completeExceptionally(exception);
        return this;
    }

    @Nonnull
    public Promise<V> supplySync(@Nonnull Supplier<V> supplier) {
        this.markAsSupplied();
        this.executeSync(new LuminePromise.SupplyRunnable(supplier));
        return this;
    }

    @Nonnull
    public Promise<V> supplyAsync(@Nonnull Supplier<V> supplier) {
        this.markAsSupplied();
        this.executeAsync(new LuminePromise.SupplyRunnable(supplier));
        return this;
    }

    @Nonnull
    public Promise<V> supplyDelayedSync(@Nonnull Supplier<V> supplier, long delayTicks) {
        this.markAsSupplied();
        this.executeDelayedSync(new LuminePromise.SupplyRunnable(supplier), delayTicks);
        return this;
    }

    @Nonnull
    public Promise<V> supplyDelayedSync(@Nonnull Supplier<V> supplier, long delay, @Nonnull TimeUnit unit) {
        this.markAsSupplied();
        this.executeDelayedSync(new LuminePromise.SupplyRunnable(supplier), delay, unit);
        return this;
    }

    @Nonnull
    public Promise<V> supplyDelayedAsync(@Nonnull Supplier<V> supplier, long delayTicks) {
        this.markAsSupplied();
        this.executeDelayedAsync(new LuminePromise.SupplyRunnable(supplier), delayTicks);
        return this;
    }

    @Nonnull
    public Promise<V> supplyDelayedAsync(@Nonnull Supplier<V> supplier, long delay, @Nonnull TimeUnit unit) {
        this.markAsSupplied();
        this.executeDelayedAsync(new LuminePromise.SupplyRunnable(supplier), delay, unit);
        return this;
    }

    @Nonnull
    public Promise<V> supplyExceptionallySync(@Nonnull Callable<V> callable) {
        this.markAsSupplied();
        this.executeSync(new LuminePromise.ThrowingSupplyRunnable(callable));
        return this;
    }

    @Nonnull
    public Promise<V> supplyExceptionallyAsync(@Nonnull Callable<V> callable) {
        this.markAsSupplied();
        this.executeAsync(new LuminePromise.ThrowingSupplyRunnable(callable));
        return this;
    }

    @Nonnull
    public Promise<V> supplyExceptionallyDelayedSync(@Nonnull Callable<V> callable, long delayTicks) {
        this.markAsSupplied();
        this.executeDelayedSync(new LuminePromise.ThrowingSupplyRunnable(callable), delayTicks);
        return this;
    }

    @Nonnull
    public Promise<V> supplyExceptionallyDelayedSync(@Nonnull Callable<V> callable, long delay, @Nonnull TimeUnit unit) {
        this.markAsSupplied();
        this.executeDelayedSync(new LuminePromise.ThrowingSupplyRunnable(callable), delay, unit);
        return this;
    }

    @Nonnull
    public Promise<V> supplyExceptionallyDelayedAsync(@Nonnull Callable<V> callable, long delayTicks) {
        this.markAsSupplied();
        this.executeDelayedAsync(new LuminePromise.ThrowingSupplyRunnable(callable), delayTicks);
        return this;
    }

    @Nonnull
    public Promise<V> supplyExceptionallyDelayedAsync(@Nonnull Callable<V> callable, long delay, @Nonnull TimeUnit unit) {
        this.markAsSupplied();
        this.executeDelayedAsync(new LuminePromise.ThrowingSupplyRunnable(callable), delay, unit);
        return this;
    }

    @Nonnull
    public <U> Promise<U> thenApplySync(@Nonnull Function<? super V, ? extends U> fn) {
        LuminePromise<U> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t != null) {
                promise.completeExceptionally(t);
            } else {
                this.executeSync(new LuminePromise.ApplyRunnable(promise, fn, value));
            }

        });
        return promise;
    }

    @Nonnull
    public <U> Promise<U> thenApplyAsync(@Nonnull Function<? super V, ? extends U> fn) {
        LuminePromise<U> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t != null) {
                promise.completeExceptionally(t);
            } else {
                this.executeAsync(new LuminePromise.ApplyRunnable(promise, fn, value));
            }

        });
        return promise;
    }

    @Nonnull
    public <U> Promise<U> thenApplyDelayedSync(@Nonnull Function<? super V, ? extends U> fn, long delayTicks) {
        LuminePromise<U> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t != null) {
                promise.completeExceptionally(t);
            } else {
                this.executeDelayedSync(new LuminePromise.ApplyRunnable(promise, fn, value), delayTicks);
            }

        });
        return promise;
    }

    @Nonnull
    public <U> Promise<U> thenApplyDelayedSync(@Nonnull Function<? super V, ? extends U> fn, long delay, @Nonnull TimeUnit unit) {
        LuminePromise<U> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t != null) {
                promise.completeExceptionally(t);
            } else {
                this.executeDelayedSync(new LuminePromise.ApplyRunnable(promise, fn, value), delay, unit);
            }

        });
        return promise;
    }

    @Nonnull
    public <U> Promise<U> thenApplyDelayedAsync(@Nonnull Function<? super V, ? extends U> fn, long delayTicks) {
        LuminePromise<U> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t != null) {
                promise.completeExceptionally(t);
            } else {
                this.executeDelayedAsync(new LuminePromise.ApplyRunnable(promise, fn, value), delayTicks);
            }

        });
        return promise;
    }

    @Nonnull
    public <U> Promise<U> thenApplyDelayedAsync(@Nonnull Function<? super V, ? extends U> fn, long delay, @Nonnull TimeUnit unit) {
        LuminePromise<U> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t != null) {
                promise.completeExceptionally(t);
            } else {
                this.executeDelayedAsync(new LuminePromise.ApplyRunnable(promise, fn, value), delay, unit);
            }

        });
        return promise;
    }

    @Nonnull
    public <U> Promise<U> thenComposeSync(@Nonnull Function<? super V, ? extends Promise<U>> fn) {
        LuminePromise<U> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t != null) {
                promise.completeExceptionally(t);
            } else {
                this.executeSync(new LuminePromise.ComposeRunnable(promise, fn, value, true));
            }

        });
        return promise;
    }

    @Nonnull
    public <U> Promise<U> thenComposeAsync(@Nonnull Function<? super V, ? extends Promise<U>> fn) {
        LuminePromise<U> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t != null) {
                promise.completeExceptionally(t);
            } else {
                this.executeAsync(new LuminePromise.ComposeRunnable(promise, fn, value, false));
            }

        });
        return promise;
    }

    @Nonnull
    public <U> Promise<U> thenComposeDelayedSync(@Nonnull Function<? super V, ? extends Promise<U>> fn, long delayTicks) {
        LuminePromise<U> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t != null) {
                promise.completeExceptionally(t);
            } else {
                this.executeDelayedSync(new LuminePromise.ComposeRunnable(promise, fn, value, true), delayTicks);
            }

        });
        return promise;
    }

    @Nonnull
    public <U> Promise<U> thenComposeDelayedSync(@Nonnull Function<? super V, ? extends Promise<U>> fn, long delay, @Nonnull TimeUnit unit) {
        LuminePromise<U> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t != null) {
                promise.completeExceptionally(t);
            } else {
                this.executeDelayedSync(new LuminePromise.ComposeRunnable(promise, fn, value, true), delay, unit);
            }

        });
        return promise;
    }

    @Nonnull
    public <U> Promise<U> thenComposeDelayedAsync(@Nonnull Function<? super V, ? extends Promise<U>> fn, long delayTicks) {
        LuminePromise<U> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t != null) {
                promise.completeExceptionally(t);
            } else {
                this.executeDelayedAsync(new LuminePromise.ComposeRunnable(promise, fn, value, false), delayTicks);
            }

        });
        return promise;
    }

    @Nonnull
    public <U> Promise<U> thenComposeDelayedAsync(@Nonnull Function<? super V, ? extends Promise<U>> fn, long delay, @Nonnull TimeUnit unit) {
        LuminePromise<U> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t != null) {
                promise.completeExceptionally(t);
            } else {
                this.executeDelayedAsync(new LuminePromise.ComposeRunnable(promise, fn, value, false), delay, unit);
            }

        });
        return promise;
    }

    @Nonnull
    public Promise<V> exceptionallySync(@Nonnull Function<Throwable, ? extends V> fn) {
        LuminePromise<V> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t == null) {
                promise.complete(value);
            } else {
                this.executeSync(new LuminePromise.ExceptionallyRunnable(promise, fn, t));
            }

        });
        return promise;
    }

    @Nonnull
    public Promise<V> exceptionallyAsync(@Nonnull Function<Throwable, ? extends V> fn) {
        LuminePromise<V> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t == null) {
                promise.complete(value);
            } else {
                this.executeAsync(new LuminePromise.ExceptionallyRunnable(promise, fn, t));
            }

        });
        return promise;
    }

    @Nonnull
    public Promise<V> exceptionallyDelayedSync(@Nonnull Function<Throwable, ? extends V> fn, long delayTicks) {
        LuminePromise<V> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t == null) {
                promise.complete(value);
            } else {
                this.executeDelayedSync(new LuminePromise.ExceptionallyRunnable(promise, fn, t), delayTicks);
            }

        });
        return promise;
    }

    @Nonnull
    public Promise<V> exceptionallyDelayedSync(@Nonnull Function<Throwable, ? extends V> fn, long delay, @Nonnull TimeUnit unit) {
        LuminePromise<V> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t == null) {
                promise.complete(value);
            } else {
                this.executeDelayedSync(new LuminePromise.ExceptionallyRunnable(promise, fn, t), delay, unit);
            }

        });
        return promise;
    }

    @Nonnull
    public Promise<V> exceptionallyDelayedAsync(@Nonnull Function<Throwable, ? extends V> fn, long delayTicks) {
        LuminePromise<V> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t == null) {
                promise.complete(value);
            } else {
                this.executeDelayedAsync(new LuminePromise.ExceptionallyRunnable(promise, fn, t), delayTicks);
            }

        });
        return promise;
    }

    @Nonnull
    public Promise<V> exceptionallyDelayedAsync(@Nonnull Function<Throwable, ? extends V> fn, long delay, @Nonnull TimeUnit unit) {
        LuminePromise<V> promise = empty();
        this.fut.whenComplete((value, t) -> {
            if (t == null) {
                promise.complete(value);
            } else {
                this.executeDelayedAsync(new LuminePromise.ExceptionallyRunnable(promise, fn, t), delay, unit);
            }

        });
        return promise;
    }

    private final class SupplyRunnable implements Runnable, Delegate<Supplier<V>> {
        private final Supplier<V> supplier;

        private SupplyRunnable(Supplier<V> supplier) {
            this.supplier = supplier;
        }

        public Supplier<V> getDelegate() {
            return this.supplier;
        }

        public void run() {
            if (!LuminePromise.this.cancelled.get()) {
                try {
                    LuminePromise.this.fut.complete(this.supplier.get());
                } catch (Throwable var2) {
                    LuminePromise.EXCEPTION_CONSUMER.accept(var2);
                    LuminePromise.this.fut.completeExceptionally(var2);
                }

            }
        }
    }

    private final class ThrowingSupplyRunnable implements Runnable, Delegate<Callable<V>> {
        private final Callable<V> supplier;

        private ThrowingSupplyRunnable(Callable<V> supplier) {
            this.supplier = supplier;
        }

        public Callable<V> getDelegate() {
            return this.supplier;
        }

        public void run() {
            if (!LuminePromise.this.cancelled.get()) {
                try {
                    LuminePromise.this.fut.complete(this.supplier.call());
                } catch (Throwable var2) {
                    LuminePromise.EXCEPTION_CONSUMER.accept(var2);
                    LuminePromise.this.fut.completeExceptionally(var2);
                }

            }
        }
    }

    private final class ExceptionallyRunnable<U> implements Runnable, Delegate<Function> {
        private final LuminePromise<U> promise;
        private final Function<Throwable, ? extends U> function;
        private final Throwable t;

        private ExceptionallyRunnable(LuminePromise<U> promise, Function<Throwable, ? extends U> function, Throwable t) {
            this.promise = promise;
            this.function = function;
            this.t = t;
        }

        public Function getDelegate() {
            return this.function;
        }

        public void run() {
            if (!LuminePromise.this.cancelled.get()) {
                try {
                    this.promise.complete(this.function.apply(this.t));
                } catch (Throwable var2) {
                    LuminePromise.EXCEPTION_CONSUMER.accept(var2);
                    this.promise.completeExceptionally(var2);
                }

            }
        }
    }

    private final class ComposeRunnable<U> implements Runnable, Delegate<Function> {
        private final LuminePromise<U> promise;
        private final Function<? super V, ? extends Promise<U>> function;
        private final V value;
        private final boolean sync;

        private ComposeRunnable(LuminePromise<U> promise, Function<? super V, ? extends Promise<U>> function, V value, boolean sync) {
            this.promise = promise;
            this.function = function;
            this.value = value;
            this.sync = sync;
        }

        public Function getDelegate() {
            return this.function;
        }

        public void run() {
            if (!LuminePromise.this.cancelled.get()) {
                try {
                    Promise<U> p = (Promise)this.function.apply(this.value);
                    if (p == null) {
                        this.promise.complete(null);
                    } else {
                        LuminePromise var10001;
                        if (this.sync) {
                            var10001 = this.promise;
                            Objects.requireNonNull(var10001);
                            p.thenAcceptSync((x$0) -> {
                                var10001.complete(x$0);
                            });
                        } else {
                            var10001 = this.promise;
                            Objects.requireNonNull(var10001);
                            p.thenAcceptAsync((x$0) -> {
                                var10001.complete(x$0);
                            });
                        }
                    }
                } catch (Throwable var2) {
                    LuminePromise.EXCEPTION_CONSUMER.accept(var2);
                    this.promise.completeExceptionally(var2);
                }

            }
        }
    }

    private final class ApplyRunnable<U> implements Runnable, Delegate<Function> {
        private final LuminePromise<U> promise;
        private final Function<? super V, ? extends U> function;
        private final V value;

        private ApplyRunnable(LuminePromise<U> promise, Function<? super V, ? extends U> function, V value) {
            this.promise = promise;
            this.function = function;
            this.value = value;
        }

        public Function getDelegate() {
            return this.function;
        }

        public void run() {
            if (!LuminePromise.this.cancelled.get()) {
                try {
                    this.promise.complete(this.function.apply(this.value));
                } catch (Throwable var2) {
                    LuminePromise.EXCEPTION_CONSUMER.accept(var2);
                    this.promise.completeExceptionally(var2);
                }

            }
        }
    }
}
